import {
	CRCTable,
	crc16_table
} from "@/utils/service.js";

import {
	TextEncoder
} from 'text-decoding';
import {
	TERMINAL_TYPE,
	READ_AND_WRITE_STATUS,
} from "@/common/config.js";
import common from '@/utils/common.js';

import {
	equipCommlog
} from "@/api/api.js";
import {
	phonePermissionSetting
} from "@/utils/permission.js";

// ArrayBuffer转16进制字符串示例
export function ab2hex(buffer) {
	let hexArr = Array.prototype.map.call(
		new Uint8Array(buffer),
		function(bit) {
			return ('00' + bit.toString(16)).slice(-2)
		}
	)
	return hexArr.join('');
}
export function hexCharCodeToStr(hexCharCodeStr) {
	var trimedStr = hexCharCodeStr.trim();
	var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
	var len = rawStr.length;
	if (len % 2 !== 0) {
		return "Illegal Format ASCII Code!";
	}
	var curCharCode;
	var resultStr = [];
	for (var i = 0; i < len; i = i + 2) {
		curCharCode = parseInt(rawStr.substr(i, 2), 16); // ASCII Code Value
		resultStr.push(String.fromCharCode(curCharCode));
	}
	return resultStr.join("");
}
// charCodeAt(i) 来获得字符串中第 i 位字符的 Unicode 编码，如果该编码 >255 ,则表示该字符占用2个字节。
export function getBytesLength(str) {
	var num = str.length; //先用num保存一下字符串的长度（可以理解为：先假设每个字符都只占用一个字节）
	for (var i = 0; i < str.length; i++) { //遍历字符串
		if (str.charCodeAt(i) > 255) { //判断某个字符是否占用两个字节，如果是，num再+1
			num++;
		}
	}
	return num; //返回最终的num，既是字符串总的字节长度
}

// 定义按位截取 ArrayBuffer 的函数
export function sliceArrayBufferByBit(arrayBuffer, start, end) {
	const byteOffset = Math.floor(start / 8);
	const byteLength = Math.ceil((end - start) / 8);
	const slicedBuffer = arrayBuffer.slice(byteOffset, byteOffset + byteLength);
	const dataView = new DataView(slicedBuffer);

	let result = '';
	for (let i = 0; i < end - start; i++) {
		const byteIndex = Math.floor(i / 8);
		const bitIndex = i % 8;
		const byte = dataView.getUint8(byteIndex);

		if ((byte >> (7 - bitIndex)) & 1) {
			result += '1';
		} else {
			result += '0';
		}
	}
	return result;
}
// 定义按位截取字符串的函数
export function sliceStringByBit(arrayBuffer, start, end) {
	const byteArray = new Uint8Array(arrayBuffer); // 根据 ArrayBuffer 创建一个 Uint8Array

	let bitString = '';
	for (let i = start; i < end; i++) {
		const byteIndex = Math.floor(i / 8);
		const bitIndex = i % 8;

		const bit = (byteArray[byteIndex] >> (7 - bitIndex)) & 1; // 获取指定位的值
		bitString += bit;
	}

	const slicedString = bitString.match(/.{1,8}/g) // 将二进制字符串每8位分组
		.map(bin => String.fromCharCode(parseInt(bin, 2))) // 将每个分组转换为字符
		.join(''); // 组装字符，生成最终截取的字符串

	return slicedString;
}
// 定义将 ArrayBuffer 转换为二进制字符串的函数
export function arrayBufferToBinaryString(arrayBuffer) {
	const view = new DataView(arrayBuffer);
	let binaryString = '';

	for (let i = 0; i < arrayBuffer.byteLength; i++) {
		const byte = view.getUint8(i);
		binaryString += byte.toString(2).padStart(8, '0');
	}

	return binaryString;
}

export function strCode(str) {
	var result = [];
	var list = str.split(" ");
	for (var i = 0; i < list.length; i++) {
		var item = list[i];
		var asciiCode = parseInt(item, 2); //对字符串进行解析（二进制转化）
		var charValue = String.fromCharCode(asciiCode);
		result.push(charValue);
	}
	return result.join("");
}
// 字符串转arraybuffer
export function string2buffer(str) {
	// 首先将字符串转为16进制
	let val = ""
	for (let i = 0; i < str.length; i++) {
		if (val === '') {
			val = str.charCodeAt(i).toString(16)
		} else {
			val += ',' + str.charCodeAt(i).toString(16)
		}
	}
	// console.log(val)
	// 将16进制转化为ArrayBuffer
	return new Uint8Array(val.match(/[\da-f]{2}/gi).map(function(h) {
		return parseInt(h, 16)
	})).buffer
}

export function removeNullUndefined(obj) {
	return Object.fromEntries(Object.entries(obj).filter(([_, v]) => v != null && v != undefined && v != '' || v ===
		0 || v === false));
}
export function doCopy(val) {
	let result;
	uni.setClipboardData({
		data: val, //要被复制的内容
		success: () => { //复制成功的回调函数
			result = true;
		},
		fail: () => {
			result = false;
		}
	});

	uni.showToast({
		icon: 'none',
		duration: 3000,
		title: `${result ? '复制成功' :'复制失败'}`
	});
}

// 地址(7bit);数据区长度(9bit)
// 将十进制数处理为 2 字节的 ArrayBuffer
export function sendDecimalValues(decimal1, decimal2) {
	// 第一个字节
	const highestBit = (decimal2 >> 8) & 1;
	const firstByte = (decimal1 & 0x7F) | (highestBit << 7);

	// 第二个字节
	const secondByte = decimal2 & 0xFF;
	const array = [firstByte, secondByte];
	return array;
}
// 命令字(1字节)
export function setBitsInByte(highBits, lowBits) {
	return ((lowBits & 0xF) << 4) | (highBits & 0xF); // 合并高位和低位
}

// const highBits = 5; // 二进制表示为 0101
// const lowBits = 6; // 二进制表示为 0110
// const buffer = setBitsInByte(highBits, lowBits);
// console.log(buffer);
// CRC16校验
export function calculateCRC16(data) {
	const crcTable = CRCTable;
	let crc = 0x0000;

	for (let i = 0; i < data.length; i++) {
		const byte = data[i];
		crc = (crc << 8) ^ crcTable[((crc >> 8) ^ byte) & 0xFF];
	}
	return crc & 0xFFFF;
}
// const data = [0x05, 0x06];
// const crc = calculateCRC16(data);

// console.log(crc.toString(16).toUpperCase()); // 输出 CRC16校验码的十六进制表示

export function sendDecimalArray(decimalArray) {
	// 将十进制数组转换为 Uint8Array
	const uint8Array = new Uint8Array(decimalArray);

	// 创建一个与十进制数组相同长度的 ArrayBuffer
	const buffer = new ArrayBuffer(decimalArray.length);

	// 将 Uint8Array 内容复制到 ArrayBuffer 中
	const view = new Uint8Array(buffer);
	view.set(uint8Array);

	// 发送 buffer 或进行其他处理
	// ...

	return buffer;
}

// const decimalArray = [254, 123, 45]; // 待发送的十进制数组

// const buffer = sendDecimalArray(decimalArray);

// console.log(new Uint8Array(buffer)); // 打印 ArrayBuffer 转换为 Uint8Array 输出
// 除法,进一法
export function divisionWithCeil(dividend, divisor) {
	return Math.ceil(dividend / divisor);
}

// const result = divisionWithCeil(10, 3);
// console.log(result); // 输出结果为 4
export function strLength(str) {
	const blob = new Blob([str]);
	const byteLength = blob.size;
	return byteLength;
}
// 16进制转Array
export function hexStringToArray(hexString) {
	return hexString.match(/.{1,2}/g).map((hexCode) => parseInt(hexCode, 16));
}
//单包发送命令
// dataUnit数据单元, operaType操作类型, addr地址, len数据区长度=rawbufflen+5, pack包号（单包取0，多包用上面的函数自动调用）, databuff数据区=snddatabuff整个数据区数组
export function DataGet(dataUnit, operaType, addr, len, pack, databuff) {
	var buff = [],
		num = 0,
		sndbuff = [];
	buff[num++] = pack;
	buff[num++] = dataUnit | (operaType << 4);
	buff[num++] = addr + ((len & 0x0100) >> 1);
	buff[num++] = len & 0xff;

	sndbuff = buff.concat(databuff);
	let crc = crc16_xmodem_nx(sndbuff, len + 4, 0x00);
	sndbuff[len + 4] = crc & 0xff;
	sndbuff[len + 5] = (crc & 0xff00) >> 8;
	return sndbuff;
}
export function crc16_xmodem_nx(data, length, crc) {
	let ii = 0;
	for (ii = 0; ii < length; ii++) {
		crc = (crc << 8) ^ crc16_table[((crc >> 8) ^ data[ii]) & 0x00FF];
	}
	return crc & 0xFFFF;
}
//组装整个databuff区,仅在数据区长度>0时用
// rawbuff数据区内被发送的数据，返回【被发送数据的总包数(1Byte)，被发送数据的总长度(2Byte)，整个数据区数组】
export function paraconfigdata(rawbuff) {
	var rawbufflen = rawbuff.length; //���ݳ���
	var totalnum = Math.ceil((rawbufflen + 5) / (512 - 6));
	var databuff = [];
	databuff[0] = totalnum;
	databuff[1] = rawbufflen & 0xff;
	databuff[2] = rawbufflen >> 8;
	var snddatabuff = databuff.concat(rawbuff);
	// console.log(snddatabuff); 
	var crc = crc16_xmodem_nx(snddatabuff, rawbufflen + 3, 0x00);
	snddatabuff[rawbufflen + 3] = crc & 0xff;
	snddatabuff[rawbufflen + 4] = (crc & 0xff00) >> 8;
	return snddatabuff;
	// return [totalnum, rawbufflen, snddatabuff];
}
//单包解析   rxbuff收到的整个单包数据 
export function Parse(rxbuff) {
	let rxlen = rxbuff.length;
	let crc = crc16_xmodem_nx(rxbuff, rxlen - 2, 0x00);
	if ((rxbuff[rxlen - 2] == (crc & 0xff)) && (rxbuff[rxlen - 1] == ((crc & 0xff00) >> 8))) {
		// console.log("crc1 ok");
		let dataUnit = rxbuff[1] & 0x0f;
		let operaType = (rxbuff[1] & 0xf0) >> 4;
		let addr = rxbuff[2] & 0x7f;
		let datalen = rxbuff[3] | ((rxbuff[2] & 0x80) << 1);
		// console.log('长度' + datalen)
		//按包填入数据区数据
		if (datalen > 0) {
			//  实际命令都是单帧                   
			let packagenum = rxbuff[4];
			let databufflen = rxbuff[5] + (rxbuff[6] << 8);
			crc = crc16_xmodem_nx(rxbuff.slice(4), rxlen - 6 - 2, 0x00);
			// console.log(crc, datalen, databufflen);
			if ((rxbuff[rxlen - 4] == (crc & 0xff)) && (rxbuff[rxlen - 3] == ((crc & 0xff00) >> 8))) {
				// console.log("crc2 ok");
				let databuff = rxbuff.slice(7, rxlen - 4);
				// console.log(rxbuff)
				// console.log(databuff)
				return {
					dataUnit,
					operaType,
					databuff
				};
				// 返回上面解析的operaType和databuff,或者在此处直接按operaType解析到具体变量
				// eg:
				// switch(operaType)
				// {
				//     case 0://状态查询

				// }
			}
		}
	}
}
export function Set1Byte(para) {
	// 将十进制数据处理成1字节数据
	const buff = para & 0xFF;
	return buff;
}
//para为处理完精度的正整数
export function Set2Byte(para) {
	var buff = [para & 0xff, para >> 8];
	return buff;
}
export function Set3Byte(para) {
	// 将数据处理成3字节
	let buff = [para & 0xFF, (para >> 8) & 0xFF, (para >> 16) & 0xFF];
	return buff;
}
export function Set4Byte(para) {
	var buff = [para & 0xff, (para >> 8) & 0xff, (para >> 16) & 0xff, (para >> 24) & 0xff];
	return buff;
}
export function Get2Byte(para) {
	// 将两个字节数据合并成16位无符号整数
	let value = (para[1] << 8) | para[0];
	return value;
}
export function Get3Byte(para) {
	let value = ((para[2] << 16) & 0xFF) | ((para[1] << 8) & 0xFF) | (para[0] & 0xFF);
	return value;
}
export function Get4Byte(para) {
	let value = (para[3] << 24) | (para[2] << 16) | (para[1] << 8) | (para[0]);
	return value;
}
//按位置1
export function BitSet(para, n) {
	para = para | (1 << n);
	return para;
}
//按位清0
export function BitClr(para, n) {
	para = para & (~(1 << n));
	return para;
}

// Array转为ArrayBuffer
export function arrayToBuffer(arr) {
	const typedArray = new Uint8Array(arr.length);
	for (let i = 0; i < arr.length; i++) {
		typedArray[i] = arr[i];
	}
	return typedArray.buffer;
}

// const arr = [10, 20, 30, 40];
// const buffer = arrayToBuffer(arr);
// console.log(buffer); // 输出 ArrayBuffer 对象
// 鉴权码20字节,不足部分补零,小端模式低字节在前
export function sendAuthString(str) {
	const encoder = new TextEncoder();
	const encoded = encoder.encode(str);
	// 创建一个 20 字节大小的 ArrayBuffer
	const buffer = new ArrayBuffer(20);

	// 使用 DataView 来操作 ArrayBuffer
	const view = new DataView(buffer);

	// 将每个字符的字节写入到 ArrayBuffer
	for (let i = 0; i < encoded.length; i++) {
		view.setUint8(i, encoded[i], true); // 第三个参数为 true，表示使用小端模式
	}
	// 返回 ArrayBuffer 对象
	return buffer;
}
// 反馈点信息量
export function feedback(array) {
	// Bit0- 1,Bit2,Bit3，Bit4，Bit5
	// [2,1,1,1,1]
	let errorstate;
	array.forEach((ele, index) => {
		if (index == 0) {
			errorstate = array[0] & 0b00000011;
		} else {
			if (ele == 1) {
				errorstate = BitSet(errorstate, index + 1);
			} else {
				errorstate = BitClr(errorstate, index + 1);
			}
		}
	});
	return errorstate;
}
// 按位处理
export function bitToStr(array) {
	let errorstate;
	array.forEach((ele, index) => {
		if (ele == 1) {
			errorstate = BitSet(errorstate, index);
		} else {
			errorstate = BitClr(errorstate, index);
		}
	});
	return errorstate;
}
// 按位取出
export function getByBite(data) { //data是传入的数据
	var byteData = data;
	var byteArr = new Array();
	// 按位取出每一位数据
	byteArr[0] = byteData & 0x01;
	byteArr[1] = (byteData >> 1) & 0x01;
	byteArr[2] = (byteData >> 2) & 0x01;
	byteArr[3] = (byteData >> 3) & 0x01;
	byteArr[4] = (byteData >> 4) & 0x01;
	byteArr[5] = (byteData >> 5) & 0x01;
	byteArr[6] = (byteData >> 6) & 0x01;
	byteArr[7] = (byteData >> 7) & 0x01;
	return byteArr;
}

// 有符号整数处理
export function hexToSignedDecimal(hexString) {
	// 将16进制字符串转换为有符号整数
	const signedDecimal = new Int8Array([parseInt(hexString, 16)]);
	return signedDecimal[0];
}
// 16进制转10进制,低字节在前
export function hecToDec(hexString) {
	// 将十六进制字符串翻转成小端模式
	let reversedHexString = hexString
		.match(/.{1,2}/g)
		.reverse()
		.join("");
	// 将翻转后的十六进制字符串转换为十进制数
	return parseInt(reversedHexString, 16); // 输出转换后的十进制数
}

// 返回上一页
export function goBack() {
	uni.navigateBack({
		delta: 1
	})
}
export function getDataTimes() {
	// 创建一个 Date 对象
	const currentDate = new Date();

	// 获取年、月、日、时、分、秒
	const year = currentDate.getFullYear();
	const month = currentDate.getMonth() < 9 ? ('0' + (currentDate.getMonth() + 1)) : (currentDate.getMonth() +
		1); // 月份是从 0 开始的，所以要加 1
	const day = currentDate.getDate() < 10 ? ('0' + currentDate.getDate()) : currentDate.getDate();
	const hours = currentDate.getHours() < 10 ? ('0' + currentDate.getHours()) : currentDate.getHours();
	const minutes = currentDate.getMinutes() < 10 ? ('0' + currentDate.getMinutes()) : currentDate.getMinutes();
	const seconds = currentDate.getSeconds() < 10 ? ('0' + currentDate.getSeconds()) : currentDate.getSeconds();
	return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}

export function isEmptyObject(object) { // 判断对象内容是否为空
	let isEmpty = false
	Object.keys(object).forEach((x) => {
		if (object[x] !== null && object[x] !== '') {
			isEmpty = true
		}
	})
	if (isEmpty) {
		return true
	} else {
		return false
	}
}

// 上传通讯日志
// requestParam,请求参数;
// resultParam,响应参数;
// statusCode,状态code
export function uploadEquipCommlog(requestParam, resultParam, typeCode, statusCode, startTime, deviceInfo, remark) {
	let terminalType;
	//#ifdef MP-WEIXIN
	terminalType = TERMINAL_TYPE[0];
	//#endif

	//#ifndef MP-WEIXIN
	let platform = uni.getSystemInfoSync().platform;
	if (platform == 'android') {
		terminalType = TERMINAL_TYPE[1];
	} else if (platform == 'ios') {
		terminalType = TERMINAL_TYPE[2];
	}
	//#endif

	let deviceType = "";
	if ((deviceInfo.localName && deviceInfo.localName.startsWith('CC')) || (deviceInfo.name && deviceInfo.name
			.startsWith('CC'))) {
		deviceType = "CC";
	} else if ((deviceInfo.localName && deviceInfo.localName.startsWith('CHZD')) || (deviceInfo.name && deviceInfo.name
			.startsWith(
				'CHZD'))) {
		deviceType = "CHZD";
	}

	// 请求成功后获取当前时间戳
	const endTime = new Date().getTime();
	let params = {
		"costTime": endTime - startTime, //时间差
		"equipCode": deviceInfo.localName || deviceInfo.name,
		"equipType": deviceType,
		"operBy": uni.getStorageSync('userName'),
		"operTime": getDataTimes(),
		"operUserId": uni.getStorageSync('userId'),
		"remark": remark,
		"requestParam": requestParam,
		"resultParam": resultParam,
		"statusCode": statusCode,
		"terminalType": terminalType,
		typeCode: typeCode,
	};
	equipCommlog('/insert', 'post', params).then(res => {});
}
// 检测蓝牙是否打开
export function checkBluetoothStatus() {
	console.log('开始检测=======')
	uni.getBluetoothAdapterState({
		success: (adapterState) => {
			console.log('检测蓝牙是否打开---------')
			console.log(adapterState)
			if (!adapterState.available) {
				uni.showModal({
					title: '提示',
					content: '请打开手机蓝牙服务功能，否则功能无法正常使用！',
					confirmColor: '#ee6666', //确定字体颜色
					showCancel: false, //没有取消按钮的弹框
					buttonText: '确定',
				})
			} else {
				// 蓝牙已打开
				// 判断定位是否开启
				uni.getSystemInfo({
					success: function(res) {
						var platform = res.platform;
						if (platform === 'android') {
							var context = plus.android.importClass("android.content.Context");
							var locationManager = plus.android.importClass(
								"android.location.LocationManager");
							var main = plus.android.runtimeMainActivity();
							var mainSvr = main.getSystemService(context.LOCATION_SERVICE);
							if (!mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER)) {
								uni.showModal({
									title: "提示",
									content: "请打开定位服务功能，否则功能无法正常使用！",
									showCancel: false,
									success() {
										if (!mainSvr.isProviderEnabled(locationManager
												.GPS_PROVIDER)) {
											var Intent = plus.android.importClass(
												"android.content.Intent");
											var Settings = plus.android.importClass(
												"android.provider.Settings");
											var intent = new Intent(Settings
												.ACTION_LOCATION_SOURCE_SETTINGDS);
											main.startActivity(intent);
										} else {
											console.log('GPS已经开启');
										}
									}
								})
							}
						}
					}
				})

				// #ifdef MP-WEIXIN
				uni.authorize({
					scope: 'scope.bluetooth',
					success(res) { //1.1 允许授权
						console.log(res)
					},
					fail(err) { //1.2 拒绝授权
						console.log(err)
						uni.showModal({
							content: '蓝牙未打开，是否跳转到设置页打开蓝牙？',
							confirmText: "确认",
							cancelText: '取消',
							success: (res) => {
								if (res.confirm) {
									uni.openSetting({
										success: (res) => {
											console.log(res);
										}
									})
								} else {
									console.log('取消');
									return false;
								}
							}
						})
						return false;
					}
				})
				// #endif

				// #ifdef APP-ANDROID
				// phonePermissionSetting();

				// #endif
			}
		},
		fail: (err) => {
			uni.showModal({
				title: '提示',
				content: '请打开手机蓝牙，否则功能无法正常使用！',
				confirmColor: '#ee6666', //确定字体颜色
				showCancel: false, //没有取消按钮的弹框
				buttonText: '确定',
			})
		}
	});
}